<h2>{@html __('publish / title') }</h2>

<div>
    <PublishButton
        {published}
        {publishing}
        {publishStarted}
        {now}
        {progress}
        {unpublished}
        {unpublishing}
        {redirectDisabled}
        needsRepublish="{needs_republish}"
        publishError="{publish_error}"
        publicVersion="{$publicVersion}"
        on:publish="publish()"
        on:unpublish="requestUnpublishConfirmation()"
    />

    {#if published}
    <ShareEmbed
        {pluginShareurls}
        {embedTemplates}
        pending="{publishing || unpublishing}"
        {shareurlType}
        {embedType}
        metadata="{$metadata}"
        id="{$id}"
        publicUrl="{$publicUrl}"
    />
    {/if}

    <!-- BEFORE EXPORT -->
    <svelte:component this="{beforeExport}" />

    <!-- EXPORT -->
    <div class="export-and-duplicate">
        <div>
            <h2 class="pad-top">{@html exportHed}</h2>
            {#if exportIntro}
            <p>{@html exportIntro}</p>
            {/if}
        </div>

        <ul class="chart-actions">
            {#each sortedChartActions as action} {#if action}
            <li
                class="
                    action action-{action.id}
                    {action.class||''}
                    {action.id
                    ==
                    active_action
                    ?
                    'active':''}
                "
            >
                <a
                    on:click|preventDefault="select(action)"
                    role="button"
                    href="{action.url ? action.url : '#'+action.id}"
                >
                    <i class="fa fa-{action.icon}"></i
                    ><span class="title">{@html action.title}</span>
                </a>
                {#if action.banner && action.banner.text != "FALSE" && action.banner.text != "-"}
                <div class="banner" style="{action.banner.style}">{action.banner.text}</div>
                {/if}
            </li>
            {/if} {/each}
        </ul>

        <svelte:component
            ref:action
            this="{Action}"
            visible="{true}"
            show="{false}"
            data="{actionData}"
            {store}
        />
    </div>
</div>

<ConfirmationModal
    ref:confirmationModal
    confirmButtonText="{__('publish / unpublish-confirmation / unpublish')}"
    confirmButtonIcon="undo"
    backButtonText="{__('publish / unpublish-confirmation / back')}"
    id="modalConfirmation"
    title="{__('publish / unpublish-confirmation / title')}"
    on:confirm="unpublish()"
>
    <p>{@html __('publish / unpublish-confirmation / explanation')}</p>
</ConfirmationModal>

<script>
    /* eslint camelcase: "off" */
    import PublishButton from '@datawrapper/controls/publish/PublishButtonControl.html';
    import { __ } from '@datawrapper/shared/l10n';
    import { trackEvent } from '@datawrapper/shared/analytics';
    import httpReq from '@datawrapper/shared/httpReq';
    import { loadScript, loadStylesheet } from '@datawrapper/shared/fetch';

    import ConfirmationModal from '@datawrapper/controls/ConfirmationModal.html';
    import ShareEmbed from './ShareEmbed.html';
    import Action from './Action.html';

    let initial_auto_publish = true;

    export default {
        components: {
            PublishButton,
            ConfirmationModal,
            ShareEmbed
        },
        data() {
            return {
                active_action: '',
                embedTemplates: [],
                pluginShareurls: [],
                published: false,
                publishing: false,
                publishStarted: 0,
                unpublished: false,
                unpublishing: false,
                needs_republish: false,
                publish_error: false,
                auto_publish: false,
                progress: [],
                redirectDisabled: false,
                shareurlType: 'default',
                embedType: 'responsive',
                Action,
                actionData: null,
                store: null,
                chartActions: [
                    {
                        id: 'duplicate',
                        icon: 'code-fork',
                        title: __('Duplicate'),
                        order: 500,
                        action: 'duplicate'
                    }
                ],
                publishHed: '',
                publishIntro: '',
                beforeExport: null,
                exportHed: __('publish / export-duplicate'),
                exportIntro: __('publish / export-duplicate / intro'),
                embedCode: '',
                statusUrl: false
            };
        },
        computed: {
            sortedChartActions({ chartActions, $actions }) {
                return chartActions
                    .concat($actions)
                    .filter(a => a.id !== 'publish-s3')
                    .sort((a, b) => a.order - b.order);
            },

            publishWait({ publishStarted, now }) {
                return publishStarted > 0 ? now - publishStarted : 0;
            }
        },
        helpers: { __ },
        methods: {
            publish() {
                this.set({
                    publishing: true,
                    publishStarted: new Date().getTime(),
                    now: new Date().getTime(),
                    progress: [],
                    unpublished: false,
                    publish_error: false
                });

                const chart = this.store;

                trackEvent('Chart Editor', 'publish');

                const chartId = chart.get().id;

                chart.store(() => {
                    this.set({
                        statusUrl: `/v3/charts/${chartId}/publish/status/${
                            chart.get().publicVersion
                        }`
                    });
                    // publish chart
                    httpReq
                        .post(`/v3/charts/${chartId}/publish`)
                        .then(() => {
                            this.set({
                                published: true,
                                progress: ['done']
                            });
                            httpReq.get(`/v3/charts/${chartId}`).then(res => {
                                trackEvent('Chart Editor', 'publish-success');
                                this.publishFinished(res);
                            });
                        })
                        .catch(error => {
                            this.set({
                                publish_error: error.message,
                                publishing: false,
                                progress: []
                            });
                            trackEvent('Chart Editor', 'publish-error', error.message);
                        });

                    setTimeout(() => {
                        const { publishing } = this.get();
                        if (publishing) this.updateStatus();
                    }, 1000);
                });
            },

            unpublish() {
                const chartId = this.store.get().id;

                this.set({
                    progress: [],
                    unpublishing: true,
                    needs_republish: false
                });

                httpReq
                    .post(`/v3/charts/${chartId}/unpublish`)
                    .then(() => {
                        httpReq.get(`/v3/charts/${chartId}`).then(chartInfo => {
                            this.store.set(chartInfo);
                            trackEvent('Chart Editor', 'unpublish-success');

                            // slow down visual response, reduces flickering:
                            setTimeout(() => {
                                this.set({
                                    published: false,
                                    unpublishing: false,
                                    unpublished: true
                                });
                            }, 1000);
                        });
                    })
                    .catch(error => {
                        this.set({ publish_error: error.message, unpublishing: false });
                        trackEvent('Chart Editor', 'unpublish-error', error.message);
                    });
            },

            requestUnpublishConfirmation() {
                this.set({ publish_error: null });
                this.refs.confirmationModal.open();
            },

            updateStatus() {
                const { statusUrl } = this.get();
                if (!statusUrl) return;
                httpReq.get(statusUrl).then(res => {
                    this.set({
                        progress: res.progress || [],
                        now: new Date().getTime()
                    });
                    const { publishing } = this.get();
                    if (publishing) {
                        setTimeout(() => {
                            this.updateStatus();
                        }, 500);
                    }
                });
            },

            publishFinished(chartInfo) {
                this.set({
                    progress: ['done'],
                    published: true,
                    publishStarted: 0,
                    needs_republish: false,
                    publishing: false
                });
                this.store.set({
                    lastEditStep: 5
                });

                window.parent.postMessage(
                    {
                        source: 'datawrapper',
                        type: 'chart-publish',
                        chartId: chartInfo.id
                    },
                    '*'
                );
                this.store.set(chartInfo);
            },

            select(action) {
                // set hash which is used to show the action module
                window.location.hash = action.id;

                const { active_action } = this.get();
                if (action.id === active_action) {
                    // unselect current action
                    this.refs.action.set({ show: false });
                    return this.set({ active_action: '', Action });
                }
                this.set({ active_action: action.id });
                if (action.mod) {
                    if (action.mod.App) {
                        this.refs.action.set({ show: false });
                        if (action.mod.data) this.refs.action.set(action.mod.data); // TODO Remove once all action plugins support the 'data' property.
                        this.set({
                            Action: action.mod.App,
                            actionData: action.mod.data,
                            store: this.store
                        });
                        this.refs.action.set({ show: true });
                    } else {
                        // todo: show loading indicator
                        this.set({ Action });
                        this.refs.action.set({ loading: true });
                        if (action.mod.css) {
                            loadStylesheet(action.mod.css);
                        }
                        loadScript(action.mod.src, () => {
                            setTimeout(() => {
                                require([action.mod.id], mod => {
                                    // todo: HIDE loading indicator
                                    Object.assign(action.mod, mod);
                                    this.set({
                                        Action: action.mod.App,
                                        actionData: action.mod.data,
                                        store: this.store
                                    });
                                    this.refs.action.set({ show: true });
                                    if (mod.init) mod.init(this.refs.action);
                                    if (action.mod.data) this.refs.action.set(action.mod.data); // TODO Remove once all action plugins support the 'data' property.
                                });
                            }, 200);
                        });
                    }
                } else if (action.action && this[action.action]) {
                    this.set({ Action });
                    this[action.action]();
                } else if (typeof action.action === 'function') {
                    this.set({ Action });
                    action.action();
                }
            },

            duplicate() {
                const { id } = this.store.get();
                trackEvent('Chart Editor', 'duplicate');
                httpReq.post(`/v3/charts/${id}/copy`).then(res => {
                    // redirect to copied chart
                    window.location.href = `/edit/${res.id}/visualize`;
                });
            }
        },

        oncreate() {
            const { lastEditStep } = this.store.get();
            this.set({ published: lastEditStep > 4 });
            // store reference to publish step
            window.dw.backend.fire('edit.publish.oncreate', this);

            // Immediately select an action, when location hash is already set.
            const activeActionId = window.location.hash.slice(1);
            if (activeActionId) {
                const { chartActions, $actions } = this.get();
                const activeAction = chartActions
                    .concat($actions)
                    .find(action => action.id === activeActionId);
                if (activeAction) {
                    this.select(activeAction);
                }
            }
        },

        onstate({ changed, current }) {
            const userDataReady = window.dw && window.dw.backend && window.dw.backend.setUserData;
            if (changed.embedType && userDataReady) {
                const data = window.dw.backend.__userData;
                if (!current.embedType || !data) return;
                data.embedType = current.embedType;
                window.dw.backend.setUserData(data);
            }
            if (changed.shareurlType && userDataReady) {
                const data = window.dw.backend.__userData;
                if (!current.shareurlType || !data) return;
                data.shareurlType = current.shareurlType;
                window.dw.backend.setUserData(data);
            }
            if (changed.published) {
                const publishStep = window.document.querySelector(
                    '.dw-create-publish .publish-step'
                );
                if (publishStep) {
                    publishStep.classList[current.published ? 'add' : 'remove']('is-published');
                }
            }
            if (changed.auto_publish) {
                if (current.auto_publish && initial_auto_publish) {
                    this.publish();
                    initial_auto_publish = false;
                    window.history.replaceState('', '', window.location.pathname);
                }
            }
        }
    };
</script>
